home *** CD-ROM | disk | FTP | other *** search
- ; -*- Mode: LISP; Package: (DEFSYS :use (LISP) :colon-mode :external); Syntax: Common-Lisp; Lowercase: Yes -*-
-
- ;;; $Id: defsystem.lisp,v 1.9 1991/10/21 15:28:28 rz Exp $
- ;;;
- ;;; A portable defsystem facility written in pure Common LISP.
- ;;;
- ;;; Copyright (c) 1987,1988,1989 Prime Computer, Inc., Natick, MA 01760
- ;;; All Rights Reserved
- ;;;
- ;;; Use and copying of this software and preparation of derivative works
- ;;; based upon this software are permitted. Any distribution of this
- ;;; software or derivative works must comply with all applicable United
- ;;; States export control laws.
- ;;;
- ;;; This software is made available AS IS, and Prime Computer Inc. makes no
- ;;; warranty about the software, its performance or its conformity to any
- ;;; specification.
- ;;;
- ;;; Any person obtaining a copy of this software is requested to send their
- ;;; name and post office or electronic mail address to:
- ;;;
- ;;; dougr@eddie.mit.edu -or- doug@enx.prime.com
- ;;;
- ;;;
-
- #| | $Log: defsystem.lisp,v $
- Revision 1.9 1991/10/21 15:28:28 rz
- *** empty log message ***
-
- Revision 1.8 1991/10/02 17:46:17 rz
- *** empty log message ***
-
- Revision 1.7 1991/08/27 18:10:05 rz
- *** empty log message ***
-
- Revision 1.6 1991/08/26 17:58:18 rz
- *** empty log message ***
-
- Revision 1.5 1991/08/16 00:15:50 rz
- *** empty log message ***
-
- Revision 1.4 1991/03/06 14:48:48 rz
- Really fixed.
-
-
- Revision 1.3 91/03/06 14:47:29 rz
- Fixed log messages?
-
- Revision 2.3 89/02/21 19:55:48 doug
- Fixed to not reset *current-system* on recursion through systems.
-
- Revision 2.2 87/12/08 10:53:42 doug
- Added *current-system*, *downcase...*
- make load,show,compile-system use *current-system* by default
- and set the *current-system*
-
- Revision 2.1 87/05/23 14:56:18 doug
- Replaced use of concatenate with make-pathname to produce a more portable
- pathname generator. Also added some declarations to quiet compiler error
- messages.
-
- Revision 2.0 87/05/04 10:52:32 doug
- First public version.
-
- Revision 1.6 87/05/01 16:23:49 doug
- Removed documentation to defsystem.mss,doc,quic
- Added :load-after dependencies.
- More error checking. Separate package for defsystem and co.
-
- Revision 1.1 87/04/25 13:00:09 doug
- Initial Revision
-
- ||#
-
- ;;; Contains definitions for defsystem, undefsystem, load-system,
- ;;; compile-system and show-system. See defsystem.doc for more
- ;;; information.
- ;;;
-
- (in-package "DEFSYS" :use '(LISP))
-
- (export '(defsystem load-system compile-system show-system *suffixes*
- *all-systems* undefsystem *defsystem-version* *defsystem-header*
- *current-system* find-system)
- )
-
- ;; Add the feature
- (push :defsystem *features*)
-
- #+LispWorks
- (push :Unix *features*)
-
- (defvar *suffixes* nil)
- (setf *suffixes*
- #+(and Symbolics 3600) '("lisp" . "bin")
- #+(and Symbolics IMach) '("lisp" . "ibin")
- #+(and dec common vax (not ultrix)) '("LSP" . "FAS")
- #+(and dec common vax ultrix) '("lsp" . "fas")
- #+KCL '("lisp" . "o")
- #+Xerox '("lisp" . "dfasl")
- #+(and Lucid MC68000) '("lisp" . "lbin")
- #+(and Lucid Sparc) '("lisp" . "sbin")
- #+(and Lucid MIPS) '("lisp" . "mbin")
- #+(and Lucid VAX VMS) '("lisp" . "vbin")
- #+(and LispWorks Sparc) '("lisp" . "wfasl")
- #+CMU '("lisp" . #.(c:backend-fasl-file-type c:*backend*))
- ;;; We don't want to use .CL files, do we? That's what
- ;;; Allegro says it wants. We'll use .LISP instead.
- #+Allegro '("lisp" . "fasl")
- #+system::cmu '("slisp" . "sfasl")
- #+PRIME '("lisp" . "pbin")
- #+HP '("l" . "b")
- #+TI '("lisp" . #.(string (si::local-binary-file-type)))
- )
-
- (defvar *downcase-path-from-module-name*
- #+UNIX T
- #-UNIX NIL)
-
- (defvar *defsystem-version*
- "$Revision: 1.9 $")
- (defvar *defsystem-header*
- "$Id: defsystem.lisp,v 1.9 1991/10/21 15:28:28 rz Exp $")
-
- (defvar *current-system* nil)
-
- (defstruct (system (:print-function print-system))
- (name "")
- (host nil) ; NIL or a string naming a host.
- (default-pathname (pathname "") :type pathname)
- (default-package nil :type symbol)
- (needed-systems nil :type list)
- (load-before-compile nil :type list)
- (module-list nil :type list) ;; internal
- (needs-update nil) ;; internal
- (modules (make-hash-table))) ;; internal
-
- (defun print-system (system stream level)
- (declare (ignore level))
- (format stream "#<System ~A>" (system-name system)))
-
- (defstruct (module (:print-function print-module))
- (name "")
- (load-before-compile nil)
- (compile-satisfies-load nil)
- (load-after nil)
- (recompile-on nil)
- (pathname nil)
- (package nil)
- (compile-function nil)
- (funcall-after nil)
- (funcall-after-args nil)
- (dtm 0);; internal
- (in-process nil);; internal
- (loaded nil);; internal
- )
-
- (defun print-module (module stream level)
- (declare (ignore level))
- (format stream "#<Module ~A>" (module-name module)))
-
- (defvar *all-systems* nil)
- (defvar *loaded-systems* nil)
-
- ;; Argument SYSTEM-NAME is unquoted here!
- (defmacro undefsystem (system-name)
- `(setq *all-systems* (remove-if #'(lambda (x)
- (string-equal (system-name x)
- ,(string system-name)))
- *all-systems*)))
-
- (defmacro defsystem (system-name options &body modules)
- `(let ((system-construct (append '(:name ,system-name) ',options))
- mod-list)
- (let ((system (apply #'make-system system-construct))
- (system-entry (find-system ',system-name :error-p nil)))
- (when system-entry
- (setq *all-systems* (delete system-entry *all-systems*)))
- (push system *all-systems*)
- (let ((system-mods (system-modules system)))
- (dolist (module ',modules)
- (let ((mod-construct (cons :name module)))
- (if (symbolp module)
- (setq mod-construct (list :name module)))
- (let ((module-structure (apply #'make-module mod-construct)))
- (push (module-name module-structure) mod-list)
- (setf (gethash (module-name module-structure) system-mods)
- module-structure)
- ))
- )
- )
- (setf (system-module-list system) (reverse mod-list))
- )
- ',system-name
- )
- )
-
- (defmacro do-default-system (system top-level)
- ;; Set system to *current-system* if NIL and set the
- ;; value of *current-system*
- `(if (and ,system ,top-level)
- (setq *current-system* ,system)
- (unless ,system
- (if *current-system*
- (setq ,system *current-system*)
- (error "Can't default, *current-system* has no value~%"))
- )
- )
- )
-
- (defun load-system (&optional system-name
- &key reload (include-components T) (top-level T)
- &aux system *load-verbose*)
- (declare (special *load-verbose*))
- (do-default-system system-name top-level)
- (setq *load-verbose* nil)
- (setq system (find-system system-name))
- ;; Load subsystems
- (when include-components
- (dolist (subsystem (system-needed-systems system))
- (when (or reload (not (member subsystem *loaded-systems*)))
- (format T "~&;;; Loading System ~S~%" subsystem)
- (load-system subsystem :reload reload :top-level NIL
- :include-components include-components))))
- ;; Load modules
- (dolist (module (system-module-list system))
- (let ((module-description (getmod module system)))
- ;; If already loaded then only reload if needed
- (load-if-needed module-description system reload)
- )
- )
- (format T ";;; Done loading system ~S~%" system-name)
- (setf (system-needs-update system) nil)
- (unless (member system-name *loaded-systems*)
- (push system-name *loaded-systems*))
- )
-
- (defun compile-load-system (&optional system-name
- &key reload recompile
- (include-components T) (top-level T))
- (do-default-system system-name top-level)
- (compile-system system-name :reload reload :top-level NIL
- :recompile recompile :include-components include-components)
- (load-system system-name :reload reload :top-level NIL
- :include-components include-components)
- )
-
- (defun compile-system (&optional system-name
- &key reload recompile (include-components T)
- (top-level T)
- &aux system
- compiled-modules *load-verbose*)
- (declare (special system compiled-modules *load-verbose*))
- (setq *load-verbose* nil)
- (do-default-system system-name top-level)
- (setq system (find-system system-name))
- ;; Recompile included systems
- (when include-components
- (dolist (subsystem (system-needed-systems system))
- (format T "~&;;; Compiling System ~S~%" subsystem)
- (compile-system subsystem
- :recompile recompile :top-level NIL
- :include-components include-components))
- )
- ;; Load Compile subsystem dependencies
- (dolist (subsystem (system-load-before-compile system))
- (when (or reload
- (not (member subsystem *loaded-systems*))
- (system-needs-update subsystem))
- (format T "~&;;; Loading System ~S~%" subsystem)
- (load-system subsystem
- :reload reload :top-level NIL
- :include-components include-components)))
- ;; Compile modules
- (dolist (module (system-module-list system))
- (compile-if-needed module reload recompile)
- )
- nil
- )
-
- (defun get-pathname (module system)
- (let ((mdp (machine-dependent-pathname
- (system-default-pathname system)
- (system-host system)))
- mpath sname bname sdtm bdtm)
- (unless (setq mpath (module-pathname module))
- (setq mpath
- (setf (module-pathname module)
- (make-pathname
- #-LispWorks :host #-LispWorks (system-host system)
- :device (pathname-device mdp)
- :directory (pathname-directory mdp)
- :name (mname-to-path (module-name module))))))
- (setq sname (make-pathname
- #-LispWorks :host #-LispWorks (pathname-host mpath)
- :directory (pathname-directory mpath)
- :device (pathname-device mpath)
- :name (pathname-name mpath)
- :type (machine-dependent-lisp-type)))
- (setq bname (make-pathname
- #-LispWorks :host #-LispWorks (pathname-host mpath)
- :directory (pathname-directory mpath)
- :device (pathname-device mpath)
- :name (pathname-name mpath)
- :type (machine-dependent-binary-type)))
- (setq sdtm (and (probe-file sname) (file-write-date sname))
- bdtm (and (probe-file bname) (file-write-date bname)))
- (cond
- ((and sdtm bdtm) ; Both exist take newer
- (if (> sdtm bdtm)
- sname
- bname))
- (bdtm bname)
- (sdtm sname)
- (T ; no file around
- (error "Can't find any file for module named ~S"
- (module-name module))))))
-
- (defun load-if-needed (module-description system &optional reload)
- (let ((path (get-pathname module-description system))
- (mdp (pathname-directory
- (machine-dependent-pathname
- (system-default-pathname system)
- (system-host system)))))
- (if (and (module-loaded module-description) (not reload))
- (when (< (module-dtm module-description)
- (file-write-date path))
- (do-load system module-description path reload)
- (setf (module-dtm module-description)
- (file-write-date path))
- )
- (progn (do-load system module-description path reload)
- (unless (module-pathname module-description)
- (setf (module-pathname module-description)
- (make-pathname
- #-LispWorks :host #-LispWorks (system-host system)
- :device (pathname-device mdp)
- :directory (pathname-directory mdp)
- :name (mname-to-path (module-name module-description))))
- )
- (setf (module-dtm module-description)
- (file-write-date path))
- (setf (module-loaded module-description) T)))))
-
- (defmacro with-package (package &body forms)
- `(if ,package
- (let ((*package* *package*))
- (setf *package* (or (find-package ,package)
- (make-package ,package)))
- ,@forms)
- (progn ,@forms)))
-
- (defun do-load (system module path &optional reload &aux package load-after)
- (when (setq load-after (module-load-after module))
- (when (symbolp load-after) (setq load-after (list load-after)))
- (dolist (m load-after)
- (load-if-needed
- (getmod m system)
- system
- reload
- ))
- )
- (format T "~&;;; Loading file ~S~%" path)
- (setq package (or (module-package module)
- (system-default-package system)))
- (with-package package
- (load path))
- ;; do funcall after stuff
- (let ((f (module-funcall-after module)))
- (when f (apply f (module-funcall-after-args module)))
- )
- )
-
-
- (defun compile-if-needed (module-name &optional reload recompile)
- (declare (special system compiled-modules))
- (let (mdp mpath sname bname module
- sdtm bdtm ddtm ddtms package
- compile-function)
- (setq module (getmod module-name system))
- (setq package (or (module-package module)
- (system-default-package system)))
- ;; Do our dependents
- (if (or (null (module-recompile-on module))
- (module-in-process module))
- (setq ddtms '(0))
- (unwind-protect
- ;; We don't want to recurse infinitely if one module has
- ;; a reciprocal compile relation with another so we set the
- ;; in-process flag to cause this to bottom out. The
- ;; unwind-protect makes sure it's cleaned up on error cases.
- (progn (setf (module-in-process module) T)
- (dolist (mod (module-recompile-on module))
- (push (compile-if-needed mod) ddtms)
- ))
- (setf (module-in-process module) nil)
- )
- )
- (setq ddtm (apply #'max ddtms))
- (unless (setq mpath (module-pathname module))
- (setq mdp (machine-dependent-pathname
- (system-default-pathname system)
- (system-host system)))
- (setq mpath
- (setf (module-pathname module)
- (make-pathname
- #-LispWorks :host #-LispWorks (system-host system)
- :device (pathname-device mdp)
- :directory (pathname-directory mdp)
- :name (mname-to-path module-name)))))
- (setq sname (make-pathname
- #-LispWorks :host #-LispWorks (pathname-host mpath)
- :directory (pathname-directory mpath)
- :device (pathname-device mpath)
- :name (pathname-name mpath)
- :type (machine-dependent-lisp-type)))
- (setq bname (make-pathname
- #-LispWorks :host #-LispWorks (pathname-host mpath)
- :directory (pathname-directory mpath)
- :device (pathname-device mpath)
- :name (pathname-name mpath)
- :type (machine-dependent-binary-type)))
- (setq sdtm (and (probe-file sname) (file-write-date sname))
- bdtm (and (probe-file bname) (file-write-date bname)))
- (unless bdtm (setq bdtm 0))
- (unless sdtm
- (error "Can't find the source file for ~S~%" module-name))
- (if (and (or (< bdtm sdtm) (< bdtm ddtm)
- (and recompile (not (member module-name compiled-modules))))
- (not (module-in-process module)))
- ;; Recompiling.. load necessary files
- (progn
- (dolist (name (module-recompile-on module))
- (load-if-needed (getmod name system) system reload)
- )
- (dolist (name (module-load-before-compile module))
- (load-if-needed (getmod name system) system reload)
- )
- (format T "~&;;; Compiling ~S..." (module-name module))
- (setq compile-function (module-compile-function module))
- (unless compile-function (setq compile-function #'compile-file))
- (with-package package
- (funcall compile-function sname))
- (when (module-compile-satisfies-load module)
- (setf (module-loaded module) T))
- (format T "~%")
- (push module-name compiled-modules)
- (setf (system-needs-update system) T)
- ;; recompiling produces a new file so...
- (get-universal-time)
- )
- ;; Not recompiling or in process..
- (max bdtm sdtm))))
-
- (defun show-system (&optional system-name &aux system)
- (do-default-system system-name T)
- (setq system (find-system system-name))
- (format T "~&;;; System: ~S~%;;;~%" (system-name system))
- (format T ";;; Needed Systems: ~S~%" (system-needed-systems system))
- (format T ";;; Default Package: ~S~%" (system-default-package system))
- (format T ";;; Default Pathname: ~S~%" (system-default-pathname system))
- (format T ";;; Load-before-compile: ~S~%" (system-load-before-compile system))
- (format T ";;; Needs update: ~S~%" (system-needs-update system))
- (format T ";;;~%")
- (dolist (module-name (system-module-list system))
- (let ((module (getmod module-name system)))
- (format T ";;; Module: ~S Package: ~S Loaded: ~S Compile-satisfies-load: ~S~%"
- module-name (module-package module)
- (module-loaded module) (module-compile-satisfies-load module)
- )
- (format T ";;; Load-before-compile: ~S ~%"
- (module-load-before-compile module))
- (format T ";;; Load-after: ~S~%"
- (module-load-after module))
- (format T ";;; Recompile-on: ~S~%" (module-recompile-on module))
- (format T ";;; Pathname: ~S~%" (module-pathname module))
- )
- )
- (format T ";;; ---------------------------------")
- )
-
- (defun getmod (m s &aux md)
- (setq md (gethash m (system-modules s)))
- (if md
- md
- (error "Module ~S not present in System ~S~%"
- m s)
- )
- )
-
- (defun mname-to-path (module)
- ;; Convert module to entryname
- ;; Under UNIX downcase by default
- (if *downcase-path-from-module-name*
- (string-downcase (string module))
- (string module)
- )
- )
-
- (defvar *system-registry* "/fsys/nori/b/tmc-hacks/Registry/")
-
- ;;; Added key argument ERROR-P to allow using find-system for seeing
- ;;; whether a system is defined yet (rick 7-20-89)
- ;;; Added use of a global system registry (rz 4-13-90)
- (defun find-system (system-name &key (error-p t))
- (flet ((find-system-try ()
- (find (string system-name) *all-systems*
- :test #'(lambda (x y)
- (string-equal x (system-name y))))))
- (let ((system-entry (find-system-try))
- system-file)
- (unless (and *system-registry* (probe-file *system-registry*))
- (setq *system-registry* nil))
- (when (and (null system-entry)
- *system-registry*
- (probe-file (setq system-file
- (concatenate *system-registry*
- (string system-name)
- ".system"))))
- (load system-file)
- (setq system-entry (find-system-try)))
- (and (null system-entry) error-p
- (error "No such system description loaded. System ~S"
- system-name))
- system-entry)))
-
-
- ;;;
- ;;; When parsing Unix pathname strings on Symbolics machines,
- ;;; the host name must be explicitly included in the string.
- ;;; Otherwise the "/"s in the string will not be treated as
- ;;; they should be (a "/" is just another character in a
- ;;; Symbolics file name)
- ;;;
- ;;; PATHNAME must be a string or a pathname.
- ;;; HOST must be NIL or a string.
- ;;;
- ;;; On Lisps running under Unix, this function just
- ;;; returns PATHNAME.
- ;;;
- ;;; On Symbolics machines -
- ;;;
- ;;; If PATHNAME is a pathname we leave it alone (i.e.
- ;;; ignore HOST) and return PATHNAME.
- ;;;
- ;;; If PATHNAME is a string, HOST and PATHNAME are
- ;;; combined to form a string containing the host spec.
- ;;; and that string is returned.
- ;;;
- (defun machine-dependent-pathname (pathname host)
- #-Genera (declare (ignore host))
- #-Genera pathname
- #+Genera
- (if (pathnamep pathname)
- pathname
- (concatenate 'string host ":" pathname)))
-
- ;;;
- ;;; Using (make-pathname ... :type "lisp") doesn't
- ;;; results in a pathname like #Pxxx.LISP instead
- ;;; of #Pxxx.lisp. Using
- ;;; (make-pathname ... :type :lisp) does what we want.
- ;;;
- (defun machine-dependent-lisp-type ()
- #-Genera (car *suffixes*)
- #+Genera (intern (string-upcase (car *suffixes*)) 'keyword))
-
- ;;; Same as above
- (defun machine-dependent-binary-type ()
- #-Genera (cdr *suffixes*)
- #+Genera (intern (string-upcase (cdr *suffixes*)) 'keyword))
-